const { require, define } = (() => {
    const moduleLoadTrigger = [];
    const moduleLoadStatus = {};
    const moduleCache = {};
    async function require(...paths) {
        const promises = [];
        paths.forEach(path => {
            if(!/\.js(\?.+)?$/.test(path))
                path += ".js";
            const scriptDom = document.createElement("script");
            scriptDom.setAttribute("src", path);
            const url = scriptDom.src;
            if(moduleLoadStatus[url])
                return promises.push(new Promise(resolve => {
                    if(!_.isArray(moduleLoadTrigger[url]))
                        moduleLoadTrigger[url] = [];
                    moduleLoadTrigger[url].push(resolve);
                }));
            moduleLoadStatus[url] = true;
            promises.push(new Promise((resolve, reject) => {
                if(moduleCache[url]) {
                    delete moduleLoadStatus[url];
                    return resolve(moduleCache[url]);
                }
                scriptDom.onload = () => {
                    (async () => {
                        if(!moduleCache[url])
                            throw new Error("module not found");
                        if(_.isError(moduleCache[url]))
                            throw moduleCache[url];
                        let module;
                        if(Object.prototype.toString.call(moduleCache[url]) === "[object Promise]")
                            module = await moduleCache[url];
                        else
                            module = moduleCache[url];
                        (moduleLoadTrigger[url] || []).forEach(trigger => trigger(module));
                        delete moduleLoadStatus[url];
                        delete moduleLoadTrigger[url];
                        return module;
                    })()
                    .then(module => resolve(module))
                    .catch(err => {
                        delete moduleLoadStatus[url];
                        delete moduleLoadTrigger[url];
                        reject(err);
                    });
                };
                scriptDom.onerror = err => {
                    delete moduleLoadStatus[url];
                    delete moduleLoadTrigger[url];
                    reject(err);
                };
                document.head.appendChild(scriptDom);
            }));
        });
        return promises.length > 1 ? Promise.all(promises) : promises[0];
    }
    function define(module = () => {}) {
        try {
            moduleCache[document.currentScript.src] = module();
        }
        catch(err) {
            moduleCache[document.currentScript.src] = err;
        }
    }
    return { require, define };
})();